#include "tcp_client.h"

client_info current_client;                        // 当前客户端数据
arr_list *client_data_list = NULL;                 // 客户端数据顺序表
arr_list *group_dialog_list = NULL;                // 群聊对话消息顺序表
int flag = 1;                                      // 用于控制两个线程是否结束
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // 线程互斥锁
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;    // 线程条件变量
int single_chat_fd;                                // 用于单聊获取数据的socket
extern int i;
int tcp_client()
{
    printf("请输入客户端名称:\n");
    scanf("%s", current_client.name);
    char img_pos[4];
    printf("请输入客户端头像(1-10):\n");
    scanf("%s",img_pos);
    strcpy(current_client.send_head_portrait_name,img_name_arr[atoi(img_pos)-1]);

    init_socket();

    pthread_t th1, th2;

    get_time_str("11");
    // 创建客户端接收数据线程
    if (pthread_create(&th1, NULL, client_recv_action, NULL) != 0)
    {
        perror("pthread_create");
    }

    // 创建客户端发送数据线程
    // if (pthread_create(&th2, NULL, client_send_action, NULL) != 0)
    // {
    //     perror("pthread_create");
    // }

    // pthread_join(th1, NULL);
    // pthread_join(th2, NULL);

    // close(current_client.client_fd); //关闭客户端连接

    return 0;
}

// socket初始化
int init_socket()
{
    struct sockaddr_in server_addr; // 服务器结构体

    // 申请网络套接字文件
    if ((current_client.client_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        perror("socket");
        return 1;
    }
    printf("申请IPV4的TCP协议的网络套接字成功\n");

    bzero(&server_addr, sizeof(struct sockaddr_in));
    //初始化服务器端的套接字，并用htons和htonl将端口和地址转成网络字节序
    server_addr.sin_family = AF_INET;                   // 指定协议是使用IPV4的协议
    server_addr.sin_port = htons(SERVER_PORT);          // 指定端口号,htons用短整型的方式转化为网络字节序
    server_addr.sin_addr.s_addr = inet_addr(SERVER_IP); //将字符串的IP地址转化为网络字节序的数据

    // 连接服务器
    if (connect(current_client.client_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in)) == -1)
    {
        perror("connect");
        return -1;
    }
    printf("[%s]连接服务器成功\n", current_client.name);

    // 发送登录信息
    client_login();
}

// 客户端接收数据
void *client_recv_action(void *args)
{
    message recv_msg; // 接收的数据
    int data_size;    // 数据的大小

    while (flag)
    {
        memset(&recv_msg, 0, sizeof(message));
        data_size = recv(current_client.client_fd, &recv_msg, sizeof(message), 0); // 从服务器读取数据
        printf("客户端接受数据:type=%c,name=%s,img=%s,text=%s\n", recv_msg.msg_type, recv_msg.name, recv_msg.send_head_portrait_name,recv_msg.text);
        if (data_size <= 0)
        {
            break;
        }
        switch (recv_msg.msg_type)
        {
        case LOGIN:
        {
            printf("login %s:%s\n", recv_msg.name, recv_msg.text);
            create_list_option(list1); // 有人登陆就重新获取数据生成左侧列表
            break;
        }
        // case AMOUNT: {
        //     client_amount = atoi(recv_msg.text);
        //     printf("client_amount=%d\n", client_amount);
        //     // 唤醒写线程
        //     pthread_cond_signal(&cond);
        //     pthread_mutex_unlock(&mutex);
        //     break;
        // }
        // case CLIENTS: {
        //     printf("%s:%s\n", recv_msg.name, recv_msg.text);
        //     break;
        // }
        case SINGLE:
        {
            client_single_recv(&recv_msg);
            break;
        }
        case GROUP:
        {
            client_group_recv(&recv_msg);
            break;
        }
        case QUIT:
        {
            printf("%s:%s\n", recv_msg.name, recv_msg.text);
            break;
        }
        default:
            break;
        }
    }
}
// // 客户端发送数据
// void *client_send_action(void *args)
// {
//     int op; // 选项
//     char ch;
//     while (flag)
//     {
//         while ((ch = getchar()) != '\n' && ch != EOF)
//             ; // 清空缓冲区
//         printf("请选择:(1)单聊 (2)群聊 (3)下线\n");
//         scanf("%d", &op);
//         switch (op)
//         {
//         case 1:
//         {
//             client_single_chat();
//             break;
//         }
//         case 2:
//         {
//             client_group_chat();
//             break;
//         }
//         case 3:
//         {
//             client_quit();
//             flag = 0;
//             break;
//         }
//         default:
//             break;
//         }
//     }
// }

// 客户端登录
void client_login()
{
    message send_msg; // 发送的数据
    memset(&send_msg, 0, sizeof(message));
    strcpy(send_msg.send_head_portrait_name,current_client.send_head_portrait_name);
    strcpy(send_msg.name, current_client.name);
    send_msg.msg_type = LOGIN;
    // strcpy(send_msg.text, "上线了");

    send(current_client.client_fd, &send_msg, sizeof(message), 0); // 客户端发送数据
}

// 客户端单聊准备
void client_single_setout()
{
    pthread_mutex_lock(&mutex);
    single_chat_socket();
    // 先从服务器获取除自己以外的客户端信息
    message send_msg; // 发送的数据
    memset(&send_msg, 0, sizeof(message));

    // 告诉服务端当前客户端需要其他客户端的信息
    strcpy(send_msg.name, current_client.name);
    send_msg.msg_type = CLIENTS;
    printf("single_chat_fd=%d,send_msg.msg_type=%c,name=%s\n", single_chat_fd, send_msg.msg_type, send_msg.name);
    send(single_chat_fd, &send_msg, sizeof(message), 0); // 客户端发送数据

    int client_amount = 0; // 客户端数量
    // 1、先获取个数，以便接收时确定数组长度
    memset(&send_msg, 0, sizeof(message));

    if (recv(single_chat_fd, &send_msg, sizeof(message), 0) > 0)
    {
        // 从服务器读取数据
        client_amount = atoi(send_msg.text);
        printf("client_amount=%d\n", client_amount);
        if (client_amount <= 0)
        {
            printf("获取数据出错\n");
            goto this_flag;
        }
        // 2、获取所有客户端信息
        client_data clients[client_amount];
        memset(clients, 0, sizeof(clients));
        if (recv(single_chat_fd, clients, sizeof(clients), 0) > 0)
        {
            if (client_data_list == NULL)
            {
                client_data_list = sequence_create();
            }

            for (int i = 0; i < client_amount; i++)
            {
                // 已经存在的名称就不存入
                if (client_name_is_exist(clients[i].name) != -1)
                {
                    continue;
                }
                client_data *new_client = malloc(sizeof(client_data));
                memset(new_client, 0, sizeof(client_data));
                new_client->fd = clients[i].fd;
                strcpy(new_client->name, clients[i].name);
                sequence_insert(client_data_list, new_client);
            }
        }
    }

this_flag:
    // 告诉服务器退出
    memset(&send_msg, 0, sizeof(message));
    send_msg.msg_type = EXIT;
    send(single_chat_fd, &send_msg, sizeof(message), 0); // 客户端发送数据
    close(single_chat_fd);

    pthread_mutex_unlock(&mutex);
}

// 客户端群聊
void client_group_chat()
{
    message send_msg; // 发送的数据
    memset(&send_msg, 0, sizeof(message));

    strcpy(send_msg.name, current_client.name);
    send_msg.msg_type = GROUP;
    printf("请输入内容\n");
    scanf("%s", send_msg.text);
    printf("Input:%s\n", send_msg.text);

    send(current_client.client_fd, &send_msg, sizeof(message), 0); // 客户端发送数据
}

// 客户端退出
void client_quit()
{
    message send_msg; // 发送的数据
    memset(&send_msg, 0, sizeof(message));

    strcpy(send_msg.name, current_client.name);
    send_msg.msg_type = QUIT;
    // strcpy(send_msg.text, "下线了");

    send(current_client.client_fd, &send_msg, sizeof(message), 0); // 客户端发送数据
}

// 客户端群发数据
void client_group_send(char *text)
{
    message send_msg; // 发送的数据
    memset(&send_msg, 0, sizeof(message));
    strcpy(send_msg.name, current_client.name);
    strcpy(send_msg.send_head_portrait_name,current_client.send_head_portrait_name);
    send_msg.msg_type = GROUP;
    send_msg.source_fd = current_client.client_fd;
    strcpy(send_msg.text, text);
    send(current_client.client_fd, &send_msg, sizeof(message) - sizeof(send_msg.text) + strlen(send_msg.text), 0); // 客户端发送数据
}

// 客户端发送单聊数据
void client_single_send(char *text, int target_fd)
{
    message send_msg; // 发送的数据
    memset(&send_msg, 0, sizeof(message));
    strcpy(send_msg.name, current_client.name);
    strcpy(send_msg.send_head_portrait_name,current_client.send_head_portrait_name);
    send_msg.msg_type = SINGLE;
    send_msg.source_fd = current_client.client_fd;
    send_msg.target_fd = target_fd;
    strcpy(send_msg.text, text);
    send(current_client.client_fd, &send_msg, sizeof(message) - sizeof(send_msg.text) + strlen(send_msg.text), 0); // 客户端发送数据
}

// 客户端接收群聊数据
void client_group_recv(message *recv_msg)
{
    // 如果是第一次对对话就创建一个与之对话的顺序表
    if (group_dialog_list == NULL)
    {
        group_dialog_list = sequence_create();
    }
    dialog_msg *new_dm = malloc(sizeof(dialog_msg));
    strcpy(new_dm->sender, recv_msg->name);
    strcpy(new_dm->text, recv_msg->text);
    strcpy(new_dm->send_head_portrait_name,recv_msg->send_head_portrait_name);
    sequence_insert(group_dialog_list, new_dm);
    // 显示当前消息
    printf("group_dialog_list->size - 1)=%d\n", group_dialog_list->size - 1);
    group_insert_message_item(group_dialog_list->size - 1);
}

// 客户端接收单聊数据
void client_single_recv(message *recv_msg)
{
    // 操作共有资源需要加锁
    pthread_mutex_lock(&mutex);
    int i;
    client_data *now_client_data = NULL;
    dialog_msg *new_dm = NULL;
    for (i = 0; i < client_data_list->size; i++)
    {
        now_client_data = ((client_data *)client_data_list->data[i]);
        printf("client_single_recv i=%d,name=%s\n", i, now_client_data->name);
        // 寻找目标地址存入
        if (strcmp(now_client_data->name, recv_msg->name) == 0)
        {
            // 如果是第一次对对话就创建一个与之对话的顺序表
            if (now_client_data->dm_list == NULL)
            {
                now_client_data->dm_list = sequence_create();
            }
            new_dm = malloc(sizeof(dialog_msg));
            strcpy(new_dm->sender, recv_msg->name);
            strcpy(new_dm->receiver, current_client.name);
            strcpy(new_dm->text, recv_msg->text);
            strcpy(new_dm->send_head_portrait_name,recv_msg->send_head_portrait_name);
            sequence_insert(now_client_data->dm_list, new_dm);
            // 如果是当前的对话,就生成一条对话标签
            // if (current_dialog != NULL && strcmp(current_dialog->name, new_dm->sender) == 0)
            // {
            //     printf("insert node ,name=%s,sender=%s,text=%s\n", current_dialog->name, new_dm->sender, new_dm->text);
            //     insert_message_item(i);
            // }
            break;
        }
    }
    // 如果是当前正在对话的客户端
    if (current_dialog != NULL && strcmp(current_dialog->name, new_dm->sender) == 0)
    {
        printf("current_dialog->dm_list->size - 1=%d\n", current_dialog->dm_list->size - 1);
        insert_message_item(current_dialog->dm_list->size - 1);
    }
    pthread_mutex_unlock(&mutex);
}

// 客户端单聊线程
int single_chat_socket()
{
    struct sockaddr_in server_addr; // 服务器结构体

    // 申请网络套接字文件
    if ((single_chat_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        perror("socket");
        return 1;
    }
    printf("申请single_chat_fd网络套接字成功\n");

    bzero(&server_addr, sizeof(struct sockaddr_in));
    //初始化服务器端的套接字，并用htons和htonl将端口和地址转成网络字节序
    server_addr.sin_family = AF_INET;                   // 指定协议是使用IPV4的协议
    server_addr.sin_port = htons(SERVER_PORT);          // 指定端口号,htons用短整型的方式转化为网络字节序
    server_addr.sin_addr.s_addr = inet_addr(SERVER_IP); //将字符串的IP地址转化为网络字节序的数据

    // 连接服务器
    if (connect(single_chat_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in)) == -1)
    {
        perror("connect");
        return -1;
    }
    printf("single_chat连接服务器成功\n");
    return 0;
}

// 当前时间
void get_time_str(char *name)
{
    struct timeval tv;
    struct timezone tz;
    struct tm *t;

    gettimeofday(&tv, &tz);
    t = localtime(&tv.tv_sec);
    printf("%s:%d-%d-%d %d:%d:%d.%ld\n", name, 1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, tv.tv_usec);
}

// 判断指定客户端名称是否存在顺序表中,存在返回在顺序表中的位置,不存在返回-1
int client_name_is_exist(char *name)
{
    for (int i = 0; i < client_data_list->size; i++)
    {
        if (strcmp(((client_data *)client_data_list->data[i])->name, name) == 0)
        {
            return i;
        }
    }
    return -1;
}